/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#include "stdafx.h"
#include <pgl/core/PGLHistogram.h>
#include <pgl/core/PGLDataTypes.h>


PGL_IMPLEMENT_DYNCREATE(CPGLHistogram, CPGLLine1D);

void CPGLHistogram::SerializeXML(CPGLArchive& ar)
{
	CString strPos;	strPos.Format(_T("%u"),(DWORD)this);
	static const TCHAR szTag[] = _T("CPGLHistogram");

	markup::CMarkupArchive& xml = *((markup::CMarkupArchive*)ar.GetMarkup());
	if(ar.IsStoring())
	{
		xml.AddChildElem(szTag);
		xml.AddChildAttrib(_T("Name"),GetName());
		xml.IntoElem();

			/////////////////////////////////////////////////////////
			// Adding base class
			CPGLLine1D::SerializeXML(ar);

			xml.AddChildElemEx( _T("NSteps"), m_histogram.GetSize() );
			xml.AddChildElemEx(_T("Normalized"), m_bNormalized);
		xml.OutOfElem();
	}
	else
	{
		if  (!xml.FindChildElem(szTag))
				return;

		xml.IntoElem();
			CPGLLine1D::SerializeXML(ar);

			UINT nSteps = 10;
			xml.FindGetChildData(_T("NSteps"), nSteps);
			m_histogram.Resize(nSteps);

			xml.FindGetChildData(_T("Normalized"), m_bNormalized);

			ComputeHistogram();

		xml.OutOfElem();
	}
}


#ifdef _DEBUG
void CPGLHistogram::Dump( CDumpContext& dc ) const
{
    // call base class function first
    CPGLLine::Dump( dc );
}
void CPGLHistogram::AssertValid() const
{
    // call inherited AssertValid first
    CPGLLine::AssertValid();

} 
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPGLHistogram::CPGLHistogram(const CPGLColor& _FrontColor, const CPGLColor& _FillColor, LPCTSTR _eDashPattern)
: CPGLLine1D( _FrontColor, _FillColor, CPGLLine::InterpolationTypeStep, CPGLLine::MarkerTypeNone, _eDashPattern),
m_bNormalized(true)
{
	SetFilled(true);	
	SetSnapBottom(true);	
	m_histogram.Resize(50);
}

CPGLHistogram& CPGLHistogram::operator = (const CPGLHistogram& h)
{
	if (this != &h )
	{
		this->CPGLLine1D::operator = ( h );

		m_bNormalized=h.m_bNormalized;
		ComputeHistogram();
	}

	return *this;
}

CPGLHistogram::~CPGLHistogram()
{
}


void CPGLHistogram::PlotLineStripGfx(gfxinterface::CGfxInterface& gfx)
{
	if (! m_pValues)
		return;

	float origin, step;
	size_t nsteps;
	m_histogram.GetLeftContainers(origin, step, nsteps);

	CPGLLinearVector x(origin, step, nsteps);
	if (m_bNormalized)
	{
		CPGLValarrayF y;
		
		m_histogram.GetNormalizedHistogram( y.GetV());
		gfx.DrawStepStrip(x, y, GetELineType() );
	}
	else
	{
		CPGLValarrayRefL y( m_histogram.GetHistogram() );
		gfx.DrawStepStrip(x, y, GetELineType() );
	}
}

void CPGLHistogram::ComputeHistogram(bool bComputeMinMax)
{
	if (!m_pValues)
		return;

	m_histogram.ResetCounters();
	m_histogram.Compute( *m_pValues, bComputeMinMax);
}

void CPGLHistogram::SetValues( CPGLDataPtr pValues, bool bComputeMinMax )
{
	CPGLLine1D::SetValues( pValues );

	ComputeHistogram(bComputeMinMax);
}



void CPGLHistogram::GetUnionExtent(gfxinterface::CGfxInterface& gfx, CPGLRectD& rExtent)
{
	CPGLLine1D::GetUnionExtent(gfx,rExtent);

	GetExtent().SetUnion(rExtent);

	rExtent.xValid = true;
	rExtent.yValid = true;
}

void CPGLHistogram::UpdateExtent(gfxinterface::CGfxInterface& gfx)
{
	if (!m_pValues)
	{
		PGL_TRACE(_T("CPGLHistogram: no values set!\n"));
		return;
	}
	ASSERT(m_pValues);
	CPGLLine1D::UpdateExtent(gfx);

	// updating...
	CPGLRectD rExtent;

	rExtent.left = m_histogram.GetMinSpectrum();
	rExtent.right = m_histogram.GetMaxSpectrum();

	rExtent.bottom = 0;
	if (m_bNormalized)
		rExtent.top = m_histogram.GetNormMaxOccurence();
	else
		rExtent.top = m_histogram.GetMaxOccurence();
	if ( rExtent.IsHeightEmpty() )
		rExtent.yValid=false;

	// setting extent
	SetExtent(rExtent);
}
